package com.yilin.tms.data.controller;

import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.*;
import com.yilin.tms.core.application.AppUtil;
import com.yilin.tms.core.application.ReturnData;
import com.yilin.tms.core.commons.annotation.SkipLoginVerify;
import com.yilin.tms.core.commons.base.BaseController;
import com.yilin.tms.core.commons.utils.ParamUtil;
import com.yilin.tms.core.components.minio.FileDealUtil;
import com.yilin.tms.core.components.minio.MinIoUploadResDTO;
import com.yilin.tms.core.entity.user.hatch.HatchPlatProduct;
import com.yilin.tms.core.remote.IUserRemote;
import com.yilin.tms.data.service.IMinOssService;
import com.yilin.tms.data.service.impl.MinOssService;
import org.apache.commons.io.FilenameUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;

@RestController
@RequestMapping("/data/upload/")
public class UploadController extends BaseController {
    @Value("${servlet.temporary-path}")
    String temporaryPath;
    
    private static Logger logger = LoggerFactory.getLogger(UploadController.class);

    @Resource
    private IMinOssService minOssService;
    @Resource
    private IUserRemote userRemote;


    /**
     * 上传BASE64图片
     */
    @RequestMapping(value = "uploadBase64Image", method = RequestMethod.POST)
    public ReturnData uploadBase64Image(String base64Image, MinOssService.UploadType uploadType, String groupPath) {
        if (uploadType == null) uploadType = MinOssService.UploadType.temp;
        if (StringUtil.isEmpty(groupPath)) groupPath = DateTimeUtil.getDateTimeByShortStr(new Date());
        MinIoUploadResDTO upload = minOssService.upload(ImageEditUtils.base64ToMultipartFile(base64Image), uploadType.path, groupPath);
        String emergencyImg = FileDealUtil.splitRex(upload.getMinFileUrl());
        return jsonView(true, "上传图片成功", emergencyImg, false);
    }
    @PostMapping("/updateBase")
    public ReturnData<String> handleFileUpload( @RequestParam("file") MultipartFile file, MinOssService.UploadType uploadType, String groupPath) {
        if (file.isEmpty()) {
            return    jsonView(false, "上传的文件不能为空");
        }
        if (uploadType == null) uploadType = MinOssService.UploadType.temp;
        if (StringUtil.isEmpty(groupPath)) groupPath = DateTimeUtil.getDateTimeByShortStr(new Date());
        try {
            String base64 = encodeFileToBase64Binary(file);
            MinIoUploadResDTO upload = minOssService.upload(ImageEditUtils.base64ToMultipartFile("data:image/jpeg;base64,"+base64), uploadType.path, groupPath);
            String emergencyImg = FileDealUtil.splitRex(upload.getMinFileUrl());
            return jsonView(true, "上传图片成功", emergencyImg, false);
        } catch (IOException e) {
            e.printStackTrace();
            return    jsonView(false, "文件上传失败：" + e.getMessage());
        }
    }
    private String encodeFileToBase64Binary(MultipartFile file) throws IOException {
        byte[] bytes = file.getBytes();
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 批量上传图片
     */
    @RequestMapping(value = "uploadImage", method = RequestMethod.POST)
    public ReturnData uploadImage(@RequestParam(value = "file", required = false) MultipartFile[] files,MinOssService.UploadType uploadType, String groupPath) {
        List<String> urls = new ArrayList<>();
        if (uploadType == null) uploadType = MinOssService.UploadType.temp;
        if (StringUtil.isEmpty(groupPath)) groupPath = DateTimeUtil.getDateTimeByShortStr(new Date());
        for (MultipartFile file : files) {
            MinIoUploadResDTO upload = minOssService.upload(file, uploadType.path, groupPath);
            urls.add(FileDealUtil.splitRex(upload.getMinFileUrl()));
        }
        String emergencyImg = String.join(",", urls);
        return jsonView(true, "上传图片成功", emergencyImg, false);
    }

    /**
     * 处理印章图片[抠图]
     */
    @RequestMapping(value = "mattingSealImg", method = RequestMethod.POST)
    public ReturnData mattingSealImg(String imageBase64) {
        if (StringUtil.isEmpty(imageBase64)) return jsonView(true, "数据为空");
        try {
            BufferedImage image = ImageEditUtils.base64ToBufferedImage(imageBase64);
            BufferedImage bufferedImage = StampFactory.getInstance().stampCutout(image);
            if (bufferedImage == null) throw new BusinessException("解析图片失败！");
            bufferedImage = StampFactory.getInstance().cropImage(bufferedImage);
            if (bufferedImage == null) throw new BusinessException("没有识别到图片印章信息！");
            String base64FromImage = ImageEditUtils.getBase64FromImage(bufferedImage);
            return jsonView(true, "抠图成功", base64FromImage);
        } catch (Exception e) {
            throw new BusinessException("印章图片解析失败，请重新采集");
        }
    }

    /**
     * 生成印章图片
     */
    @RequestMapping(value = "generateSealImg", method = RequestMethod.POST)
    public ReturnData generateSealImg(String type) {
        try {
            HatchPlatProduct platProduct = ParamUtil.isSuccess(userRemote.getPlatProductHatch(getLoginUser().getOrganizeId()));
            if (platProduct == null) return jsonErrView("仅网货平台允许生成电子印章,产品参数为空");
            String elSeal ; //////////////////////////////////////////////////////////////////////
            if (type.equals("receiptSeal")) elSeal = SealUtil.buildElSeal(platProduct.getPlatName(), platProduct.getProductName(), "物流回单专用章");
            else elSeal = SealUtil.buildCrSeal(platProduct.getPlatName(), "合同专用章");
            MinIoUploadResDTO upload = minOssService.upload(ImageEditUtils.base64ToMultipartFile(elSeal), MinOssService.UploadType.auth.path, "seal");
            String emergencyImg = FileDealUtil.splitRex(upload.getMinFileUrl());
            return jsonView(true, "上传图片成功", emergencyImg,false);
        } catch (Exception e) {
            throw new BusinessException("电子印章生成失败，请重试！");
        }
    }

    /**
     * 上传聊天图片 返回缩略图
     */
    @ResponseBody
    @RequestMapping(value = "uploadMessageImage", method = RequestMethod.POST)
    public ReturnData uploadMessageImage(@RequestParam(value = "file", required = false) MultipartFile[] files) {
        Map<String, Object> retMap = new HashMap<>();
        try {
            //保存上传源文件
            MinIoUploadResDTO upload = minOssService.upload(files[0], MinOssService.UploadType.chat.path, "image");
            retMap.put("originalUrl", FileDealUtil.splitRex(upload.getMinFileUrl()));
            //保存缩略图 2
            File temp1File = FileDealUtil.saveTempFile(files[0], AppUtil.getTemporaryPath(temporaryPath));
            File temp2File = FileDealUtil.createTempFile(AppUtil.getTemporaryPath(temporaryPath), FilenameUtils.getExtension(temp1File.getName()));
            ImageEditUtils.compressPic(temp1File, temp2File, 300, 300);
            //上传缩略图 2
            MultipartFile multipartFile = FileDealUtil.getMultipartFile(temp2File);
            MinIoUploadResDTO upload2 = minOssService.upload(multipartFile, MinOssService.UploadType.thumb.path, "image");
            retMap.put("thumbUrl", FileDealUtil.splitRex(upload2.getMinFileUrl()));
            //存储完成：删除临时文件
            boolean delete = false;
            if (temp1File.exists()) delete = temp1File.delete();
            if (temp2File.exists()) delete = temp2File.delete();
            logger.info("上传完成：删除临时文件：" + (delete ? "成功" : "失败"));
            return jsonView(true, "上传图片成功", retMap, false);
        } catch (Exception e) {
            throw new BusinessException("图片上传失败，请重新上传");
        }
    }

    /**
     * 上传聊天语音
     */
    @RequestMapping(value = "uploadMessageVoice", method = RequestMethod.POST)
    @ResponseBody
    public ReturnData uploadMessageVoice(@RequestParam(value = "file", required = false) MultipartFile[] files) {
        Map<String, Object> retMap = new HashMap<>();
        MinIoUploadResDTO upload = minOssService.upload(files[0], MinOssService.UploadType.chat.path, "voice");
        retMap.put("originalUrl", FileDealUtil.splitRex(upload.getMinFileUrl()));
        //获取语音时长
        File temp1File = FileDealUtil.saveTempFile(files[0], AppUtil.getTemporaryPath(temporaryPath), false);
        Float duration = AudioUtil.getDuration(temp1File.getPath());
        retMap.put("voiceDuration", duration);
        //存储完成：删除临时文件
        boolean delete = false;
        if (temp1File.exists()) delete = temp1File.delete();
        logger.info("上传完成：删除临时文件：" + (delete ? "成功" : "失败"));
        return jsonView(true, "上传语音成功", retMap, false);
    }

    /**
     * 上传聊天视频
     */
    @RequestMapping(value = "uploadMessageVideo", method = RequestMethod.POST)
    @ResponseBody
    public ReturnData uploadMessageVideo(@RequestParam(value = "file", required = false) MultipartFile[] files) {
        MinIoUploadResDTO upload = minOssService.upload(files[0], MinOssService.UploadType.chat.path, "video");
        Map<String, Object> retMap = new HashMap<>();
        retMap.put("originalUrl", FileDealUtil.splitRex(upload.getMinFileUrl()));
        //获取封面图片
        File temp1File = FileDealUtil.saveTempFile(files[0], AppUtil.getTemporaryPath(temporaryPath), false);
        File temp2File = FileDealUtil.createTempFile(AppUtil.getTemporaryPath(temporaryPath), FilenameUtils.getExtension(temp1File.getName()));
        VideoCaptureUtil.fetchFrameToFile(temp1File, temp2File, 1);
        //上传封面图片
        MultipartFile multipartFile = FileDealUtil.getMultipartFile(temp2File);
        MinIoUploadResDTO upload2 = minOssService.upload(multipartFile, MinOssService.UploadType.chat.path, "video");
        retMap.put("coverUrl", FileDealUtil.splitRex(upload2.getMinFileUrl()));
        //存储完成：删除临时文件
        boolean delete = false;
        if (temp1File.exists()) delete = temp1File.delete();
        if (temp2File.exists()) delete = temp2File.delete();
        logger.info("上传完成：删除临时文件：" + (delete ? "成功" : "失败"));
        return jsonView(true, "上传视频成功", retMap, false);
    }

    /**
     * 上传聊天文件
     */
    @RequestMapping(value = "uploadMessageFile", method = RequestMethod.POST)
    @ResponseBody
    public ReturnData uploadMessageFile(@RequestParam(value = "file", required = false) MultipartFile[] files) {
        MinIoUploadResDTO upload = minOssService.upload(files[0], MinOssService.UploadType.chat.path, "file");
        Map<String, Object> retMap = new HashMap<>();
        retMap.put("originalUrl", FileDealUtil.splitRex(upload.getMinFileUrl()));
        retMap.put("fileName", files[0].getOriginalFilename());
        return jsonView(true, "上传文件成功", retMap, false);
    }

    /**
     * 上传app
     */
    @RequestMapping(value = "uploadApp", method = RequestMethod.POST)
    @ResponseBody
    public ReturnData uploadApp(@RequestParam(value = "file", required = false) MultipartFile[] files) {
        MinIoUploadResDTO upload = minOssService.upload(files[0], MinOssService.UploadType.app.path, "app");
        return jsonView(true, "上传文件成功", FileDealUtil.splitRex(upload.getMinFileUrl()), false);
    }

    /**
     * 上传广告文件
     */
    @RequestMapping(value = "uploadBannerFile", method = RequestMethod.POST)
    @ResponseBody
    public ReturnData uploadBannerFile(@RequestParam(value = "file", required = false) MultipartFile[] files) {
        MinIoUploadResDTO upload = minOssService.upload(files[0], MinOssService.UploadType.banner.path, "banner");
        return jsonView(true, "上传文件成功", FileDealUtil.splitRex(upload.getMinFileUrl()), false);
    }
}
